<template>
  <view class="forecast-maintenance">
    <!-- 左侧主工作区 -->
    <scroll-view 
      class="main-workspace" 
      scroll-y
      :style="{ width: workspaceWidth + 'px' }"
      :scroll-into-view="scrollIntoView"
      scroll-with-animation
    >
      <!-- 预报配置卡片 -->
      <view id="card-settings" class="card-section" :class="{ collapsed: collapsedSections.settings }">
        <view class="card-header" @click="toggleSection('settings')">
          <text class="card-title">预报配置</text>
          <text class="collapse-icon">{{ collapsedSections.settings ? '▼' : '▲' }}</text>
        </view>
        <view class="card-body" v-if="!collapsedSections.settings">
          <ForecastSettings 
            v-model:settings="forecastSettings"
            @settings-change="handleSettingsChange"
          />
        </view>
      </view>

      <!-- 模型参数配置卡片 -->
      <view id="card-params" class="card-section" :class="{ collapsed: collapsedSections.params }" v-if="selectedScheme">
        <view class="card-header" @click="toggleSection('params')">
          <text class="card-title">模型参数配置</text>
          <text class="collapse-icon">{{ collapsedSections.params ? '▼' : '▲' }}</text>
        </view>
        <view class="card-body" v-if="!collapsedSections.params">
          <ModelParamsConfig 
            :model-type="selectedScheme"
            v-model:params="modelParams"
            @params-change="handleParamsChange"
          />
        </view>
      </view>

      <!-- 降雨数据编辑卡片 -->
      <view id="card-rainfall" class="card-section" :class="{ collapsed: collapsedSections.rainfall }">
        <view class="card-header" @click="toggleSection('rainfall')">
          <text class="card-title">降雨数据编辑</text>
          <text class="collapse-icon">{{ collapsedSections.rainfall ? '▼' : '▲' }}</text>
        </view>
        <view class="card-body" v-if="!collapsedSections.rainfall">
          <RainfallEditor 
            v-model:data="rainfallData"
            :start-time="forecastSettings.startTime"
            :prdt="forecastSettings.prdt"
            @data-change="handleRainfallChange"
          />
        </view>
      </view>

      <!-- 预报结果展示卡片 -->
      <view id="card-result" class="card-section" :class="{ collapsed: collapsedSections.result }" v-if="currentResult">
        <view class="card-header" @click="toggleSection('result')">
          <text class="card-title">预报结果</text>
          <text class="collapse-icon">{{ collapsedSections.result ? '▼' : '▲' }}</text>
        </view>
        <view class="card-body" v-if="!collapsedSections.result">
          <ForecastEditor 
            :result="currentResult"
            :start-time="forecastSettings.startTime"
            :prdt="forecastSettings.prdt"
          />
        </view>
      </view>

      <!-- 执行按钮 -->
      <view class="action-bar">
        <button 
          class="execute-btn" 
          :class="{ executing: isExecuting, disabled: !canExecute || (hasExecuted && !sessionId) }"
          :disabled="isExecuting || !canExecute || (hasExecuted && !sessionId)"
          @click="executeForecast"
        >
          <text class="btn-icon">{{ getExecuteButtonIcon() }}</text>
          <text class="btn-text">{{ getExecuteButtonText() }}</text>
        </button>
        <view class="session-hint" v-if="hasExecuted && !sessionId && selectedScheme">
          <text class="hint-icon">⚠️</text>
          <text class="hint-text">预报会话已失效，请重新加载参数或切换方案</text>
        </view>
      </view>
    </scroll-view>

    <!-- 拖拽分隔条 -->
    <view 
      class="resizer" 
      @mousedown="startResize"
      @touchstart="startResize"
    ></view>

    <!-- 右侧LLM对话面板 -->
    <view class="chat-panel" :style="{ width: chatPanelWidth + 'px' }">
      <ChatPanel 
        ref="chatPanelRef"
        :stcd="stcd"
        :selected-scheme="selectedScheme"
        :session-id="sessionId"
        :last-session-id="lastSessionId"
        :current-params="modelParams"
        :forecast-start-time="forecastSettings.startTime"
        @command="handleChatCommand"
        @scheme-change="handleSchemeChange"
        @params-updated="handleLLMParamsUpdated"
        @open-hypothetical-rainfall="handleOpenHypotheticalRainfall"
      />
    </view>

    <!-- 版本对比弹窗 -->
    <VersionCompare 
      v-if="showCompare"
      :version1="compareVersions[0]"
      :version2="compareVersions[1]"
      @close="showCompare = false"
    />
  </view>
</template>

<script>
import { ref, reactive, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'
import { v4 as uuidv4 } from 'uuid'
import ModelParamsConfig from './config/ModelParamsConfig.vue'
import ForecastSettings from './config/ForecastSettings.vue'
import RainfallEditor from './config/RainfallEditor.vue'
import ForecastEditor from './editors/ForecastEditor.vue'
import ForecastResult from './editors/ForecastResult.vue'
import ChatPanel from './chat/ChatPanel.vue'
import { forecastApi } from './api/api.js'

export default {
  name: 'ForecastMaintenance',
  components: {
    ModelParamsConfig,
    ForecastSettings,
    RainfallEditor,
    ForecastEditor,
    ForecastResult,
    ChatPanel
  },
  props: {
    stcd: {
      type: String,
      required: true
    }
  },
  setup(props) {
    // 布局相关
    const workspaceWidth = ref(0)
    const chatPanelWidth = ref(0)
    const isResizing = ref(false)

    // 卡片折叠状态
    const collapsedSections = reactive({
      settings: false,
      params: false,
      rainfall: false,
      result: false
    })

    // 数据状态
    const selectedScheme = ref(null)
    const modelParams = ref(null)
    const forecastSettings = ref({
      startTime: getDefaultStartTime(),
      prdt: 30,        // 预热期（天）
      clen: 3,         // 预见期（天）
      rainfall_clen: 3, // 降雨预见期（天），默认等于预见期
      timeStep: 8      // 默认8时段/天
    })
    const rainfallData = ref([])
    const rainfallGribId = ref('') // 降雨预报的网格数据ID
    const currentResult = ref(null)
    const isExecuting = ref(false)
    const scrollIntoView = ref('')
    const chatPanelRef = ref(null)
    
    // Session管理
    const sessionId = ref(null)
    const lastSessionId = ref(null) // 保存上次执行的sessionId，用于恢复
    const hasExecuted = ref(false) // 标记是否已经执行过预报

    // 🔍 调试：监控 lastSessionId 的变化
    watch(lastSessionId, (newVal, oldVal) => {
      console.log('🔍 [index.vue] lastSessionId 变化:', {
        oldVal,
        newVal,
        hasValue: !!newVal,
        timestamp: new Date().toISOString()
      })
    })

    // 🔍 调试：监控 sessionId 的变化
    watch(sessionId, (newVal, oldVal) => {
      console.log('🔍 [index.vue] sessionId 变化:', {
        oldVal,
        newVal,
        hasValue: !!newVal,
        timestamp: new Date().toISOString()
      })
    })

    // 版本对比
    const showCompare = ref(false)
    const compareVersions = ref([])

    // 初始化布局尺寸
    const initLayout = () => {
      const windowWidth = window.innerWidth
      workspaceWidth.value = windowWidth * 0.55
      chatPanelWidth.value = windowWidth * 0.45
    }

    // 拖拽调整大小
    const startResize = (e) => {
      isResizing.value = true
      e.preventDefault()
      
      const onMouseMove = (moveEvent) => {
        if (!isResizing.value) return
        
        const clientX = moveEvent.clientX || moveEvent.touches?.[0]?.clientX
        if (clientX) {
          const windowWidth = window.innerWidth
          const newWorkspaceWidth = clientX
          const newChatWidth = windowWidth - clientX - 4 // 4px for resizer
          
          // 限制最小宽度
          if (newWorkspaceWidth >= 400 && newChatWidth >= 300) {
            workspaceWidth.value = newWorkspaceWidth
            chatPanelWidth.value = newChatWidth
          }
        }
      }

      const onMouseUp = () => {
        isResizing.value = false
        document.removeEventListener('mousemove', onMouseMove)
        document.removeEventListener('mouseup', onMouseUp)
        document.removeEventListener('touchmove', onMouseMove)
        document.removeEventListener('touchend', onMouseUp)
      }

      document.addEventListener('mousemove', onMouseMove)
      document.addEventListener('mouseup', onMouseUp)
      document.addEventListener('touchmove', onMouseMove)
      document.addEventListener('touchend', onMouseUp)
    }

    // 切换卡片折叠状态
    const toggleSection = (section) => {
      collapsedSections[section] = !collapsedSections[section]
    }

    // 获取默认开始时间（今天早8点）
    function getDefaultStartTime() {
      const now = new Date()
      now.setHours(8, 0, 0, 0)
      // 使用本地时间格式，避免时区转换问题
      const year = now.getFullYear()
      const month = String(now.getMonth() + 1).padStart(2, '0')
      const day = String(now.getDate()).padStart(2, '0')
      const hours = String(now.getHours()).padStart(2, '0')
      const minutes = String(now.getMinutes()).padStart(2, '0')
      return `${year}-${month}-${day}T${hours}:${minutes}`
    }

    // 事件处理
    const handleSchemeChange = async (schemeData) => {
      // 切换方案：生成全新的 sessionId，清空保存的sessionId，重置已执行标记
      sessionId.value = uuidv4()
      lastSessionId.value = null  // 清空保存的sessionId，因为这是全新的方案
      hasExecuted.value = false
      console.log('切换方案，生成全新的 sessionId:', sessionId.value)
      
      // schemeData 可能是字符串（旧格式）或对象（新格式）
      let scheme, modelId
      
      if (typeof schemeData === 'string') {
        scheme = schemeData
      } else if (typeof schemeData === 'object') {
        // 使用中文名称作为scheme标识，用于参数配置组件
        scheme = schemeData.modelTypeCN || schemeData.value || schemeData.scheme
        modelId = schemeData.id
      }
      
      selectedScheme.value = scheme
      await loadModelParams(scheme, modelId)
      // 选择方案后加载降雨数据
      await loadRainfallData()
    }
    
    // 处理LLM参数更新
    const handleLLMParamsUpdated = (newParams) => {
      console.log('📥 index.vue 收到 LLM 更新参数:', newParams)
      console.log('📥 initialState:', newParams.initialState)
      console.log('📥 parameters:', newParams.parameters)
      
      // 深拷贝确保触发响应式更新
      modelParams.value = JSON.parse(JSON.stringify(newParams))
      
      console.log('✅ modelParams.value 已更新:', modelParams.value)
      
    }

    const handleParamsChange = async (changedParams) => {
      // 参数修改时的 sessionId 处理
      if (hasExecuted.value && lastSessionId.value) {
        // 如果已执行过且有保存的sessionId，恢复它
        sessionId.value = lastSessionId.value
        hasExecuted.value = false
        console.log('参数修改，恢复之前的 sessionId:', sessionId.value)
      } else if (!sessionId.value) {
        // 如果没有sessionId，生成新的（首次选择方案后的情况）
        sessionId.value = uuidv4()
        hasExecuted.value = false
        console.log('参数修改，生成新的 sessionId:', sessionId.value)
      }
      
      // 如果有 sessionId，保存参数到后端
      if (sessionId.value && changedParams) {
        try {
          await forecastApi.updateModelParams(sessionId.value, changedParams)
          console.log('参数已保存到服务器')
        } catch (error) {
          console.error('保存参数失败:', error)
          // 不影响用户继续操作，只是日志记录
        }
      }
    }

    const handleSettingsChange = async () => {
      // 预报时段修改时的 sessionId 处理（先设置sessionId，再加载降雨数据）
      if (hasExecuted.value && lastSessionId.value) {
        // 如果已执行过且有保存的sessionId，恢复它
        sessionId.value = lastSessionId.value
        hasExecuted.value = false
        console.log('预报时段修改，恢复之前的 sessionId:', sessionId.value)
      } else if (!sessionId.value) {
        // 如果没有sessionId，生成新的
        sessionId.value = uuidv4()
        hasExecuted.value = false
        console.log('预报时段修改，生成新的 sessionId:', sessionId.value)
      }
      
      // 当预报配置改变时，重新加载降雨数据（会自动保存到session）
      console.log('handleSettingsChange 被调用，开始重新加载降雨数据')
      await loadRainfallData()
    }

    // 加载降雨数据
    const loadRainfallData = async () => {
      if (!forecastSettings.value.startTime || !forecastSettings.value.prdt || !forecastSettings.value.rainfall_clen) {
        console.log('加载降雨数据：缺少必要参数', {
          startTime: forecastSettings.value.startTime,
          prdt: forecastSettings.value.prdt,
          rainfall_clen: forecastSettings.value.rainfall_clen
        })
        return
      }
      
      try {
        console.log('开始加载降雨数据，参数:', {
          stcd: props.stcd,
          startTime: forecastSettings.value.startTime,
          prdt: forecastSettings.value.prdt,
          rainfall_clen: forecastSettings.value.rainfall_clen
        })
        
        // 格式化时间为 API 需要的格式
        const startTime = new Date(forecastSettings.value.startTime)
          .toISOString()
          .replace('T', ' ')
          .slice(0, 19)
        
        const result = await forecastApi.getRainfallData(
          props.stcd,
          startTime,
          forecastSettings.value.prdt,
          forecastSettings.value.rainfall_clen,
          sessionId.value  // 传入sessionId以自动保存降雨数据
        )
        
        console.log('降雨数据加载成功，数据点数:', result.data.length)
        rainfallData.value = result.data
        // 保存降雨网格数据ID
        rainfallGribId.value = result.metadata?.id || ''
      } catch (error) {
        console.error('加载降雨数据失败:', error)
        uni.showToast({
          title: '加载降雨数据失败: ' + error.message,
          icon: 'none',
          duration: 3000
        })
      }
    }

    const handleRainfallChange = async () => {
      // 降雨数据修改时的 sessionId 处理
      if (hasExecuted.value && lastSessionId.value) {
        // 如果已执行过且有保存的sessionId，恢复它
        sessionId.value = lastSessionId.value
        hasExecuted.value = false
        console.log('降雨数据修改，恢复之前的 sessionId:', sessionId.value)
      } else if (!sessionId.value) {
        // 如果没有sessionId，生成新的
        sessionId.value = uuidv4()
        hasExecuted.value = false
        console.log('降雨数据修改，生成新的 sessionId:', sessionId.value)
      }
      
      // 保存降雨数据到后端
      if (sessionId.value && rainfallData.value.length > 0) {
        try {
          const rainfallForBackend = rainfallData.value.map(item => ({
            time: new Date(item.time).toISOString().replace('T', ' ').slice(0, 19),
            rain: item.value
          }))
          
          await forecastApi.updateRainfall(sessionId.value, rainfallForBackend, rainfallGribId.value)
          console.log('✅ 降雨数据已保存到session')
        } catch (error) {
          console.error('❌ 保存降雨数据失败:', error)
          uni.showToast({
            title: '保存降雨数据失败',
            icon: 'none'
          })
        }
      }
    }

    // 滚动到指定卡片
    const scrollToCard = (cardId) => {
      // 卡片ID映射
      const cardMap = {
        'view_params': 'params',
        'config_time': 'settings',
        'edit_rainfall': 'rainfall',
        'view_result': 'result',
        'goto_settings': 'settings',
        'goto_params': 'params',
        'goto_rainfall': 'rainfall'
      }
      
      const targetCard = cardMap[cardId] || cardId
      
      // 如果卡片是折叠的，先展开
      if (collapsedSections[targetCard] !== undefined && collapsedSections[targetCard]) {
        collapsedSections[targetCard] = false
        
        // 显示展开提示
        uni.showToast({
          title: '正在展开...',
          icon: 'none',
          duration: 500
        })
        
        // 等待展开动画完成后滚动
        setTimeout(() => {
          scrollIntoView.value = `card-${targetCard}`
          // 重置，以便下次可以再次触发
          setTimeout(() => {
            scrollIntoView.value = ''
          }, 1000)
        }, 300)
      } else {
        scrollIntoView.value = `card-${targetCard}`
        // 重置，以便下次可以再次触发
        setTimeout(() => {
          scrollIntoView.value = ''
        }, 1000)
      }
    }

    const handleChatCommand = (command) => {
      // 处理LLM对话命令
      console.log('Chat command:', command)
      
      // 解析命令并执行相应操作
      // 注意：switch_scheme 命令现在在 ChatPanel 内部处理，不会传到这里
      if (command.type === 'select_scheme') {
        handleSchemeChange(command.scheme)
      } else if (command.type === 'execute_forecast' && canExecute.value) {
        executeForecast()
      } else if (command.type) {
        // 尝试滚动到对应卡片
        scrollToCard(command.type)
      }
    }
    
    // LLM 预填充数据
    const llmHypotheticalConfig = ref(null)
    
    // 处理 LLM 触发的假拟降雨
    const handleOpenHypotheticalRainfall = (config) => {
      console.log('🌧️ [Index] 收到假拟降雨配置:', config)
      
      // 检查 lastSessionId
      if (!lastSessionId.value) {
        console.error('❌ lastSessionId 为空，无法打开假拟降雨')
        uni.showToast({
          title: '请先执行一次预报',
          icon: 'none'
        })
        return
      }
      
      // 保存 LLM 配置
      llmHypotheticalConfig.value = config
      
      // 打开假拟降雨弹窗（在 ChatPanel 中通过命令触发）
      // 实际上应该由 ChatPanel 直接打开，这里只是备用
      console.log('✅ [Index] 假拟降雨配置已保存，等待弹窗打开')
    }

    // 加载模型参数
    const loadModelParams = async (scheme, modelId) => {
      try {
        const params = await forecastApi.getModelParams(props.stcd, scheme, modelId, sessionId.value)
        modelParams.value = params
      } catch (error) {
        console.error('加载模型参数失败:', error)
        uni.showToast({
          title: '加载模型参数失败',
          icon: 'none'
        })
      }
    }


    // 执行预报
    const executeForecast = async () => {
      if (isExecuting.value) return
      
      // 检查 sessionId
      if (!sessionId.value) {
        chatPanelRef.value?.addSystemMessage(
          `🔒 预报会话已失效\n\n当前无法执行预报计算。预报会话在执行完成后会自动失效，这是为了保证数据一致性。\n\n**恢复会话的操作**（修改后会自动恢复之前的会话）：\n• 修改模型参数\n• 修改降雨数据\n• 修改预报时段\n\n**或者切换到其他预报方案**（创建全新会话）`,
          [
            { label: '📝 修改参数', command: 'view_params', type: 'primary' },
            { label: '🌧️ 修改降雨', command: 'edit_rainfall', type: 'primary' },
            { label: '⚙️ 修改时段', command: 'config_time', type: 'primary' },
            { label: '🔄 切换方案', command: 'switch_scheme', type: 'secondary' }
          ]
        )
        
        uni.showToast({
          title: '会话已失效，请重新配置',
          icon: 'none',
          duration: 2000
        })
        return
      }
      
      // 检查必要数据
      const missingItems = []
      if (!selectedScheme.value) missingItems.push('预报方案')
      if (!modelParams.value) missingItems.push('模型参数')
      if (!rainfallData.value || rainfallData.value.length === 0) missingItems.push('降雨数据')
      
      if (missingItems.length > 0) {
        // 在聊天面板显示缺少的数据
        chatPanelRef.value?.addSystemMessage(
          `❌ 无法执行预报，缺少以下数据：\n\n${missingItems.map(item => `• ${item}`).join('\n')}\n\n请先完成以下操作：`,
          missingItems.map(item => {
            if (item === '预报方案') return { label: '👉 选择方案', command: 'select_scheme' }
            if (item === '模型参数') return { label: '📝 查看参数', command: 'view_params' }
            if (item === '降雨数据') return { label: '⚙️ 配置时间', command: 'config_time' }
          }).filter(Boolean)
        )
        return
      }
      
      isExecuting.value = true
      
      try {
        // 第1步：保存参数到服务器
        chatPanelRef.value?.addSystemMessage(
          '💾 正在保存模型参数...'
        )
        
        try {
          await forecastApi.updateModelParams(sessionId.value, modelParams.value)
          console.log('✅ 参数已保存到服务器')
          
          chatPanelRef.value?.addSystemMessage(
            '✅ 参数保存成功'
          )
        } catch (error) {
          console.error('❌ 保存参数失败:', error)
          chatPanelRef.value?.addSystemMessage(
            `⚠️ 参数保存失败：${error.message}，但仍然继续执行预报`
          )
        }
        
        // 第2步：提交任务
        chatPanelRef.value?.addSystemMessage(
          '🚀 正在提交预报任务...'
        )
        
        const taskInfo = await forecastApi.executeForecast({
          stcd: props.stcd,
          scheme: selectedScheme.value,
          params: modelParams.value,
          settings: forecastSettings.value,
          rainfallData: rainfallData.value,
          sessionId: sessionId.value
        })
        
        console.log('任务已提交, taskId:', taskInfo.taskId)
        
        // 第3步：轮询任务结果
        const progressMessageId = chatPanelRef.value?.addSystemMessage(
          `✅ 任务已提交 (ID: ${taskInfo.taskId})\n\n⏳ 正在执行模型计算，请稍候...\n\n进度：等待中...`
        )
        
        let lastProgressUpdate = Date.now()
        const result = await forecastApi.pollTaskResult(
          taskInfo.taskId,
          (progress) => {
            console.log(progress)
            // 每5秒更新一次进度显示（避免过于频繁）
            const now = Date.now()
            if (now - lastProgressUpdate > 5000) {
              chatPanelRef.value?.addSystemMessage(
                `⏳ ${progress}`
              )
              lastProgressUpdate = now
            }
          }
        )
        
        console.log('任务执行完成:', result)
        
        // 转换结果格式以适配 ForecastEditor
        currentResult.value = {
          modelName: result.modelName,
          modelVersion: result.modelVersion,
          computeTime: result.computeTime,
          warmUpPeriods: result.warmUpPeriods,
          forecastPeriods: result.forecastPeriods,
          forecastStartTime: result.forecastStartTime,
          timeSeries: result.timeSeries,
          stateTimeSeries: result.stateTimeSeries,
          finalState: result.finalState,
          modelParameters: result.modelParameters,
          metadata: result.metadata
        }
        
        // 在聊天面板显示执行成功
        const totalPeriods = result.warmUpPeriods + result.forecastPeriods
        chatPanelRef.value?.addSystemMessage(
          `✅ 预报执行成功！\n\n已生成 ${totalPeriods} 个时段的预报结果（预热期: ${result.warmUpPeriods}, 预见期: ${result.forecastPeriods}），正在跳转到结果区域...`,
          [
            { label: '📊 查看结果', command: 'view_result' }
          ]
        )
        
        // 显示提示消息
        uni.showToast({
          title: '预报执行成功，正在跳转...',
          icon: 'success',
          duration: 1500
        })
        
        // 自动展开结果卡片并平滑滚动
        setTimeout(() => {
          collapsedSections.result = false
          // 等待展开动画完成后滚动
          setTimeout(() => {
            scrollToCard('result')
          }, 300)
        }, 500)
        
        // 获取分析报告
        try {
          console.log('🔍 开始获取分析报告，sessionId:', sessionId.value)
          const report = await forecastApi.getAnalysisReport(sessionId.value)
          console.log('📊 分析报告获取成功:', report)
          
          // 在聊天面板显示markdown报告
          if (report && report.markdownReport) {
            console.log('📝 准备显示markdown报告，长度:', report.markdownReport.length)
            console.log('📄 Markdown内容:', report.markdownReport.substring(0, 200))
            console.log('🔍 chatPanelRef.value:', chatPanelRef.value)
            console.log('🔍 chatPanelRef.value?.addSystemMessage:', chatPanelRef.value?.addSystemMessage)
            
            // 检查 chatPanelRef 是否存在
            if (!chatPanelRef.value) {
              console.error('❌ chatPanelRef.value 为空！')
              return
            }
            
            if (!chatPanelRef.value.addSystemMessage) {
              console.error('❌ addSystemMessage 方法不存在！')
              return
            }
            
            // 立即显示，不要延迟
            try {
              const added = chatPanelRef.value.addSystemMessage(
                report.markdownReport,
                [],
                true  // isMarkdown = true
              )
              console.log('✅ 报告已添加到聊天面板:', added)
            } catch (err) {
              console.error('❌ 添加消息失败:', err)
            }
          } else {
            console.warn('⚠️ 报告为空或没有markdownReport字段')
          }
        } catch (error) {
          console.error('❌ 获取分析报告失败:', error)
          // 显示错误提示
          chatPanelRef.value?.addSystemMessage(
            `⚠️ 获取分析报告失败：${error.message}`
          )
        }
        
        // 执行完成后保存并清除 sessionId，并标记已执行
        console.log('预报执行完成，保存并清除 sessionId:', sessionId.value)
        lastSessionId.value = sessionId.value  // 保存sessionId，供后续恢复使用
        hasExecuted.value = true
        sessionId.value = null
        console.log('✅ lastSessionId 已设置为:', lastSessionId.value)
        
        // 在聊天面板提示会话已失效
        setTimeout(() => {
          chatPanelRef.value?.addSystemMessage(
            `✅ 预报计算完成，会话已自动失效\n\n为保证数据一致性，每次执行预报后会话会自动失效。\n\n**可执行以下操作恢复会话**：`,
            [
              { label: '📝 修改参数', command: 'view_params', type: 'primary' },
              { label: '🌧️ 修改降雨', command: 'edit_rainfall', type: 'primary' },
              { label: '⚙️ 修改时段', command: 'config_time', type: 'primary' },
              { label: '🔄 切换方案', command: 'switch_scheme', type: 'secondary' }
            ]
          )
        }, 2000)
      } catch (error) {
        console.error('执行预报失败:', error)
        
        // 显示失败Toast
        uni.showToast({
          title: '预报执行失败',
          icon: 'error',
          duration: 2000
        })
        
        // 在聊天面板显示详细错误信息
        chatPanelRef.value?.addSystemMessage(
          `❌ 预报执行失败\n\n错误信息：${error.message || '未知错误'}\n\n请检查配置后重试。`,
          [
            { label: '📝 查看参数', command: 'view_params' },
            { label: '⚙️ 查看配置', command: 'config_time' }
          ]
        )
        
        // 执行失败也保存并清除 sessionId，并标记已执行
        console.log('预报执行失败，保存并清除 sessionId:', sessionId.value)
        lastSessionId.value = sessionId.value  // 保存sessionId，供后续恢复使用
        hasExecuted.value = true
        sessionId.value = null
        console.log('⚠️ lastSessionId 已设置为（失败）:', lastSessionId.value)
        
        // 提示需要重新配置
        setTimeout(() => {
          chatPanelRef.value?.addSystemMessage(
            `⚠️ 预报执行失败，会话已失效\n\n请检查配置后重新开始。可执行以下操作恢复会话：`,
            [
              { label: '📝 检查参数', command: 'view_params', type: 'primary' },
              { label: '🌧️ 检查降雨', command: 'edit_rainfall', type: 'primary' },
              { label: '⚙️ 检查时段', command: 'config_time', type: 'primary' },
              { label: '🔄 切换方案', command: 'switch_scheme', type: 'secondary' }
            ]
          )
        }, 1000)
      } finally {
        isExecuting.value = false
      }
    }

    // 是否可以执行预报
    const canExecute = computed(() => {
      return selectedScheme.value && 
             modelParams.value && 
             rainfallData.value.length > 0
    })
    
    // 获取执行按钮图标
    const getExecuteButtonIcon = () => {
      if (isExecuting.value) return '⏳'
      if (!selectedScheme.value) return '❓'
      if (hasExecuted.value && !sessionId.value) return '🔒'
      if (!canExecute.value) return '⚠️'
      return '🚀'
    }
    
    // 获取执行按钮文本
    const getExecuteButtonText = () => {
      if (isExecuting.value) return '执行中...'
      if (!selectedScheme.value) return '请先选择方案'
      if (hasExecuted.value && !sessionId.value) return 'Session已失效'
      if (!modelParams.value) return '请先加载参数'
      if (!rainfallData.value || rainfallData.value.length === 0) return '请先配置降雨'
      return '执行预报'
    }

    // 初始化
    onMounted(() => {
      initLayout()
      window.addEventListener('resize', initLayout)
      // 初始加载降雨数据
      loadRainfallData()
      
      // 检查chatPanelRef是否正确绑定
      nextTick(() => {
        console.log('🔍 onMounted - chatPanelRef.value:', chatPanelRef.value)
        console.log('🔍 onMounted - chatPanelRef.value?.addSystemMessage:', chatPanelRef.value?.addSystemMessage)
        if (!chatPanelRef.value) {
          console.error('❌ ChatPanel ref未正确绑定！')
        }
      })
    })

    onUnmounted(() => {
      window.removeEventListener('resize', initLayout)
    })

    return {
      workspaceWidth,
      chatPanelWidth,
      collapsedSections,
      selectedScheme,
      modelParams,
      forecastSettings,
      rainfallData,
      currentResult,
      isExecuting,
      showCompare,
      compareVersions,
      canExecute,
      scrollIntoView,
      chatPanelRef,
      hasExecuted,
      sessionId,
      lastSessionId,  // 🔥 关键：必须导出才能在模板中使用
      toggleSection,
      startResize,
      handleSchemeChange,
      handleParamsChange,
      handleSettingsChange,
      handleRainfallChange,
      handleChatCommand,
      handleLLMParamsUpdated,
      handleOpenHypotheticalRainfall,  // 🔥 新增：LLM触发假拟降雨
      executeForecast,
      scrollToCard,
      getExecuteButtonIcon,
      getExecuteButtonText
    }
  }
}
</script>

<style scoped>
.forecast-maintenance {
  display: flex;
  height: 100vh;
  background-color: #f5f7fa;
  overflow: hidden;
}

.main-workspace {
  flex-shrink: 0;
  height: 100vh;
  padding: 20px;
  background-color: #f5f7fa;
}

.resizer {
  width: 4px;
  background-color: #dcdfe6;
  cursor: col-resize;
  flex-shrink: 0;
  transition: background-color 0.2s;
}

.resizer:hover {
  background-color: #409eff;
}

.chat-panel {
  flex-shrink: 0;
  background-color: #fff;
  border-left: 1px solid #e4e7ed;
  overflow: hidden;
}

/* 卡片样式 */
.card-section {
  background-color: #fff;
  border-radius: 8px;
  margin-bottom: 16px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  transition: all 0.3s;
}

.card-section.collapsed {
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.06);
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 16px 20px;
  border-bottom: 1px solid #f0f0f0;
  cursor: pointer;
  user-select: none;
  transition: background-color 0.2s;
}

.card-header:hover {
  background-color: #f8f9fa;
}

.card-section.collapsed .card-header {
  border-bottom: none;
}

.card-title {
  font-size: 16px;
  font-weight: 600;
  color: #303133;
}

.collapse-icon {
  color: #909399;
  font-size: 12px;
  transition: transform 0.3s;
}

.card-body {
  padding: 20px;
  animation: slideDown 0.3s ease-out;
}

.result-notice {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 24px;
  background: linear-gradient(135deg, #e3f2fd 0%, #f5f5f5 100%);
  border-radius: 8px;
  border: 1px solid #bbdefb;
}

.notice-icon {
  font-size: 24px;
  flex-shrink: 0;
}

.notice-text {
  font-size: 14px;
  color: #546e7a;
  line-height: 1.6;
}

@keyframes slideDown {
  from {
    opacity: 0;
    transform: translateY(-10px);
  }
  to {
    opacity: 1;
    transform: translateY(0);
  }
}

/* 操作栏 */
.action-bar {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  background-color: #fff;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  position: sticky;
  z-index: 10;
  bottom: 0px;
}

.execute-btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  padding: 10px 24px;
  background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
  color: #fff;
  border: none;
  border-radius: 8px;
  font-size: 15px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
  box-shadow: 0 4px 12px rgba(102, 126, 234, 0.3);
  position: relative;
  overflow: hidden;
}

.execute-btn::before {
  content: '';
  position: absolute;
  top: 0;
  left: -100%;
  width: 100%;
  height: 100%;
  background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.2), transparent);
  transition: left 0.5s;
}

.execute-btn:hover:not([disabled]) {
  transform: translateY(-2px);
  box-shadow: 0 6px 16px rgba(102, 126, 234, 0.4);
}

.execute-btn:hover:not([disabled])::before {
  left: 100%;
}

.execute-btn:active:not([disabled]) {
  transform: translateY(0px);
  box-shadow: 0 2px 8px rgba(102, 126, 234, 0.3);
}

.execute-btn.executing {
  background: linear-gradient(135deg, #ffd89b 0%, #19547b 100%);
  animation: pulse 2s infinite;
}

.execute-btn[disabled] {
  opacity: 0.7;
  cursor: wait;
}

.execute-btn.disabled {
  background: linear-gradient(135deg, #c0c4cc 0%, #909399 100%);
  cursor: not-allowed;
  opacity: 0.6;
}

.execute-btn.disabled:hover {
  transform: none;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
}

.btn-icon {
  font-size: 18px;
  line-height: 1;
}

.btn-text {
  font-size: 15px;
  font-weight: 600;
  letter-spacing: 0.3px;
}

@keyframes pulse {
  0%, 100% {
    box-shadow: 0 4px 12px rgba(255, 216, 155, 0.3);
  }
  50% {
    box-shadow: 0 6px 16px rgba(255, 216, 155, 0.5);
  }
}

/* Session 提示 */
.session-hint {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 16px;
  background-color: #fff3e0;
  border: 1px solid #ffb74d;
  border-radius: 6px;
  animation: shake 0.5s ease-in-out;
  max-width: 100%;
}

.hint-icon {
  font-size: 16px;
  flex-shrink: 0;
}

.hint-text {
  font-size: 13px;
  color: #e65100;
  line-height: 1.5;
  flex: 1;
}

@keyframes shake {
  0%, 100% {
    transform: translateX(0);
  }
  25% {
    transform: translateX(-5px);
  }
  75% {
    transform: translateX(5px);
  }
}

/* 滚动条样式 */
.main-workspace::-webkit-scrollbar {
  width: 8px;
}

.main-workspace::-webkit-scrollbar-track {
  background: #f1f1f1;
}

.main-workspace::-webkit-scrollbar-thumb {
  background: #c1c1c1;
  border-radius: 4px;
}

.main-workspace::-webkit-scrollbar-thumb:hover {
  background: #a8a8a8;
}
</style>

